package org.molgenis.data.postgresql;
import org.molgenis.data.Entity;
import org.molgenis.data.Query;
import org.molgenis.data.QueryRule;
import org.molgenis.data.meta.model.Attribute;
import org.molgenis.data.meta.model.EntityType;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.transaction.PlatformTransactionManager;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import javax.sql.DataSource;
import static com.google.common.collect.Lists.newArrayList;
import static java.util.Collections.singletonList;
import static java.util.stream.Collectors.toList;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.molgenis.data.QueryRule.Operator.EQUALS;
import static org.molgenis.data.meta.AttributeType.*;
import static org.testng.Assert.assertEquals;
public class PostgreSqlRepositoryTest
{
private PostgreSqlRepository postgreSqlRepo;
private JdbcTemplate jdbcTemplate;
private PostgreSqlEntityFactory postgreSqlEntityFactory;
@BeforeMethod
public void setUpBeforeMethod() throws Exception
{
postgreSqlEntityFactory = mock(PostgreSqlEntityFactory.class);
jdbcTemplate = mock(JdbcTemplate.class);
DataSource dataSource = mock(DataSource.class);
PlatformTransactionManager transactionManager = mock(PlatformTransactionManager.class);
postgreSqlRepo = new PostgreSqlRepository(postgreSqlEntityFactory, jdbcTemplate, dataSource);
}
// TODO test all query operators for one-to-many
@Test
public void countQueryOneToManyEquals() throws Exception
{
String oneToManyAttrName = "oneToManyAttr";
EntityType entityType = createEntityMetaOneToMany(oneToManyAttrName);
//noinspection unchecked
Query<Entity> query = mock(Query.class);
int queryValue = 2;
QueryRule queryRule = new QueryRule(oneToManyAttrName, EQUALS, queryValue);
when(query.getRules()).thenReturn(singletonList(queryRule));
String sql = "SELECT COUNT(DISTINCT this.\"entityId\") FROM \"Entity\" AS this LEFT JOIN \"RefEntity\" AS \"oneToManyAttr_filter1\" ON (this.\"entityId\" = \"oneToManyAttr_filter1\".\"xrefAttr\") WHERE \"oneToManyAttr_filter1\".\"refEntityId\" = ?";
long count = 123L;
when(jdbcTemplate.queryForObject(sql, new Object[] { queryValue }, Long.class)).thenReturn(count);
postgreSqlRepo.setEntityType(entityType);
assertEquals(postgreSqlRepo.count(query), count);
}
@Test
public void findAllQueryOneToManyEquals() throws Exception
{
String oneToManyAttrName = "oneToManyAttr";
EntityType entityType = createEntityMetaOneToMany(oneToManyAttrName);
//noinspection unchecked
Query<Entity> query = mock(Query.class);
int queryValue = 2;
QueryRule queryRule = new QueryRule(oneToManyAttrName, EQUALS, queryValue);
when(query.getRules()).thenReturn(singletonList(queryRule));
String sql = "SELECT DISTINCT this.\"entityId\", (SELECT array_agg(\"refEntityId\" ORDER BY \"refEntityId\" ASC) FROM \"RefEntity\" WHERE this.\"entityId\" = \"RefEntity\".\"xrefAttr\") AS \"oneToManyAttr\" FROM \"Entity\" AS this LEFT JOIN \"RefEntity\" AS \"oneToManyAttr_filter1\" ON (this.\"entityId\" = \"oneToManyAttr_filter1\".\"xrefAttr\") WHERE \"oneToManyAttr_filter1\".\"refEntityId\" = ? LIMIT 1000";
//noinspection unchecked
RowMapper<Entity> rowMapper = mock(RowMapper.class);
when(postgreSqlEntityFactory.createRowMapper(entityType, null)).thenReturn(rowMapper);
Entity entity0 = mock(Entity.class);
when(jdbcTemplate.query(sql, new Object[] { queryValue }, rowMapper)).thenReturn(singletonList(entity0));
postgreSqlRepo.setEntityType(entityType);
assertEquals(postgreSqlRepo.findAll(query).collect(toList()), singletonList(entity0));
}
private static EntityType createEntityMetaOneToMany(String oneToManyAttrName)
{
String refIdAttrName = "refEntityId";
Attribute refIdAttr = mock(Attribute.class);
when(refIdAttr.getName()).thenReturn(refIdAttrName);
when(refIdAttr.getDataType()).thenReturn(INT);
String xrefAttrName = "xrefAttr";
Attribute xrefAttr = mock(Attribute.class);
when(xrefAttr.getName()).thenReturn(xrefAttrName);
when(xrefAttr.getDataType()).thenReturn(XREF);
EntityType refEntityMeta = mock(EntityType.class);
String refEntityName = "RefEntity";
when(refEntityMeta.getName()).thenReturn(refEntityName);
when(refEntityMeta.getIdAttribute()).thenReturn(refIdAttr);
when(refEntityMeta.getAttribute(refIdAttrName)).thenReturn(refIdAttr);
when(refEntityMeta.getAttribute(xrefAttrName)).thenReturn(xrefAttr);
String idAttrName = "entityId";
Attribute idAttr = mock(Attribute.class);
when(idAttr.getName()).thenReturn(idAttrName);
when(idAttr.getDataType()).thenReturn(STRING);
Attribute oneToManyAttr = mock(Attribute.class);
when(oneToManyAttr.getName()).thenReturn(oneToManyAttrName);
when(oneToManyAttr.getDataType()).thenReturn(ONE_TO_MANY);
when(oneToManyAttr.getRefEntity()).thenReturn(refEntityMeta);
when(oneToManyAttr.isMappedBy()).thenReturn(true);
when(oneToManyAttr.getMappedBy()).thenReturn(xrefAttr);
EntityType entityType = mock(EntityType.class);
String entityName = "Entity";
when(entityType.getName()).thenReturn(entityName);
when(entityType.getIdAttribute()).thenReturn(idAttr);
when(entityType.getAttribute(idAttrName)).thenReturn(idAttr);
when(entityType.getAttribute(oneToManyAttrName)).thenReturn(oneToManyAttr);
when(entityType.getAtomicAttributes()).thenReturn(newArrayList(idAttr, oneToManyAttr));
return entityType;
}
}